using System;
using System.Diagnostics;
using System.Windows.Threading;
using System.Threading;
using System.Threading.Tasks;
using WPFApplication = System.Windows.Application;

namespace WpfApp1.Core
{
    public class ClipboardMonitor : IDisposable
    {
        private static readonly object _lock = new object();
        private static string _lastContent = string.Empty;
        private static readonly DispatcherTimer _timer;
        private static bool _isMonitoring;
        private static bool _isSettingContent;
        private static readonly int _maxRetries = 3;
        private static readonly int _retryDelayMs = 200;
        private static readonly int _maxWaitTimeMs = 500;
        private static Dispatcher _dispatcher;
        private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
        private static bool _isDisposed;

        public static event EventHandler<string>? ContentChanged;

        static ClipboardMonitor()
        {
            _dispatcher = WPFApplication.Current.Dispatcher;
            _timer = new DispatcherTimer
            {
                Interval = TimeSpan.FromSeconds(1)
            };
            _timer.Tick += Timer_Tick;
        }

        public static void Start()
        {
            if (!_isMonitoring)
            {
                _isMonitoring = true;
                _timer.Start();
            }
        }

        public static void Stop()
        {
            if (_isMonitoring)
            {
                _isMonitoring = false;
                _timer.Stop();
            }
        }

        private static async void Timer_Tick(object? sender, EventArgs e)
        {
            if (_isSettingContent || !_isMonitoring || _isDisposed) return;

            try
            {
                if (!await _semaphore.WaitAsync(TimeSpan.FromMilliseconds(_maxWaitTimeMs)))
                {
                    return;
                }

                try
                {
                    string? content = await GetClipboardContentAsync();
                    if (!string.IsNullOrEmpty(content) && content != _lastContent)
                    {
                        _lastContent = content;
                        ContentChanged?.Invoke(null, content);
                    }
                }
                finally
                {
                    _semaphore.Release();
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"监控剪贴板时出错: {ex.Message}");
            }
        }

        public static async Task<string?> GetClipboardContentAsync()
        {
            for (int retryCount = 0; retryCount < _maxRetries; retryCount++)
            {
                try
                {
                    return await _dispatcher.InvokeAsync(() =>
                    {
                        try
                        {
                            return System.Windows.Clipboard.ContainsText()
                                ? System.Windows.Clipboard.GetText()
                                : null;
                        }
                        catch (Exception ex)
                        {
                            if (retryCount == _maxRetries - 1)
                            {
                                Debug.WriteLine($"获取剪贴板内容失败: {ex.Message}");
                            }
                            return null;
                        }
                    });
                }
                catch (Exception)
                {
                    if (retryCount < _maxRetries - 1)
                    {
                        await Task.Delay(_retryDelayMs);
                    }
                }
            }
            return null;
        }

        public static async Task<bool> SetContentAsync(string content)
        {
            if (string.IsNullOrEmpty(content) || _isDisposed) return false;

            try
            {
                _isSettingContent = true;

                if (!await _semaphore.WaitAsync(TimeSpan.FromMilliseconds(_maxWaitTimeMs)))
                {
                    return false;
                }

                try
                {
                    for (int retryCount = 0; retryCount < _maxRetries; retryCount++)
                    {
                        try
                        {
                            await _dispatcher.InvokeAsync(() =>
                            {
                                System.Windows.Clipboard.SetText(content);
                                _lastContent = content;
                            });
                            return true;
                        }
                        catch (Exception ex)
                        {
                            if (retryCount == _maxRetries - 1)
                            {
                                Debug.WriteLine($"设置剪贴板内容失败: {ex.Message}");
                                return false;
                            }
                            await Task.Delay(_retryDelayMs);
                        }
                    }
                }
                finally
                {
                    _semaphore.Release();
                }
            }
            finally
            {
                _isSettingContent = false;
            }
            return false;
        }

        public static void SetContent(string content)
        {
            if (string.IsNullOrEmpty(content) || _isDisposed) return;

            try
            {
                _isSettingContent = true;
                var task = SetContentAsync(content);
                task.Wait(_maxWaitTimeMs * _maxRetries);
            }
            finally
            {
                _isSettingContent = false;
            }
        }

        public void Dispose()
        {
            if (!_isDisposed)
            {
                _isDisposed = true;
                Stop();
                _semaphore.Dispose();
            }
        }
    }
} 